package sdl2_impl

import (
	"code.google.com/p/go8/chip8"
	"code.google.com/p/go8/engine"
	"code.google.com/p/go8/games"
	"github.com/gonutz/go-sdl2/sdl"
	"github.com/gonutz/go-sdl2/sdl_image"
	"github.com/gonutz/go-sdl2/sdl_ttf"
	"strings"
)

type MenuPainter struct {
	renderer    *sdl.Renderer
	fonts       *Fonts
	game        *games.Game
	texture     *sdl.Texture
	allTextures []*sdl.Texture
}

const TextureWidth = 640

func NewMenuPainter(r *sdl.Renderer, fonts *Fonts) *MenuPainter {
	return &MenuPainter{renderer: r, fonts: fonts}
}

func (p *MenuPainter) ReleaseAllTextures() {
	for _, t := range p.allTextures {
		t.Destroy()
	}
}

func (p *MenuPainter) PaintMenu(game *games.Game) engine.Image {
	p.game = game
	p.texture = img.LoadTexture(p.renderer, "menu.png")
	//p.createScreen()
	p.allTextures = append(p.allTextures, p.texture)
	return NewImage(p.renderer, p.texture)
}

func (p *MenuPainter) createScreen() {
	p.createTextureToDrawTo()
	y := int32(0)
	y = p.line(p.fonts.Header, p.game.Name, y, sdl.Color{255, 255, 0, 255})
	y = p.line(p.fonts.SubHeader, p.game.Description, y, sdl.Color{255, 255, 128, 255})
	y += 25
	y = p.drawScreenShot(p.game.ScreenShot, y)
	y += 15
	for _, l := range SplitHowTo(p.game.HowToPlay) {
		y = p.line(p.fonts.Text, l, y, sdl.Color{255, 255, 255, 255})
	}
	p.renderer.SetRenderTarget(nil)
}

func (p *MenuPainter) createTextureToDrawTo() {
	p.texture = sdl.CreateTexture(p.renderer,
		sdl.PIXELFORMAT_RGB888, sdl.TEXTUREACCESS_TARGET,
		TextureWidth, TextureWidth/2)
	p.renderer.SetRenderTarget(p.texture)
	p.renderer.SetDrawColor(0, 0, 0, 255)
	p.renderer.Clear()
}

func (p *MenuPainter) line(font *ttf.Font, text string, y int32, c sdl.Color) (newY int32) {
	if len(text) > 0 {
		surface := font.RenderText_Solid(text, c)
		defer surface.Free()
		texture := p.renderer.CreateTextureFromSurface(surface)
		defer texture.Destroy()
		w := TextureWidth
		p.renderer.Copy(texture, nil, &sdl.Rect{int32(w/2) - surface.W/2, y, surface.W, surface.H})
		return y + surface.H
	}
	return y
}

func (p *MenuPainter) drawScreenShot(shot [32]uint64, atY int32) int32 {
	screen := &chip8.IntScreen{shot}
	atX := horizontalCenter(screen)
	p.renderer.SetDrawColor(255, 255, 255, 255)
	p.drawBorder(atX, atY, screen)
	p.drawPixels(atX, atY, screen)
	_, screenHeight := screen.Size()
	return atY + int32(screenHeight) + 2
}

func horizontalCenter(screen chip8.Screen) int32 {
	screenW, _ := screen.Size()
	return int32(TextureWidth/2 - screenW/2)
}

func (p *MenuPainter) drawBorder(x, y int32, screen chip8.Screen) {
	w, h := screen.Size()
	p.renderer.DrawRect(&sdl.Rect{x - 1, y - 1, int32(w) + 2, int32(h) + 2})
}

func (p *MenuPainter) drawPixels(atX, atY int32, screen chip8.Screen) {
	sW, sH := screen.Size()
	screenW, screenH := int32(sW), int32(sH)
	points := make([]sdl.Point, 0, 4*screenW)
	for x := int32(0); x < screenW; x++ {
		for y := int32(0); y < screenH; y++ {
			if screen.IsSet(int(x), int(y)) {
				points = append(points, sdl.Point{atX + x, atY + y})
			}
		}
	}
	if len(points) > 0 {
		p.renderer.DrawPoints(points)
	}
}

func SplitHowTo(howTo string) []string {
	howTo = strings.Replace(howTo, "\t", "", -1)
	return strings.Split(howTo, "\n")
}
